#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include<string.h>
#include <signal.h>
#include "sc.h"
#include "logger.h"


void crypt(char* str, char* secret_key, int len, int firstTime) {
	int i=0;
	static int k=0; //è statica perchè ad ogni chiamata di funzione deve partire dallo stesso punto della chiave a fare xor
	if (firstTime) {
		k = 0;
	}
	for(i=0;i<len;i++) {
		str[i] = str[i] ^ secret_key[k];
		if(++k >= strlen(secret_key))
			k=0;
	}
	return;
}


void signal_catch(int signo) {
	serverLog("Unlink FIFO!");
	unlink("ClientToServer");
	unlink("ServerToClient");
	serverLog("Close Server!");
	closeLogger();
	exit(0);
}




int main() {
	initLogger();
	serverLog("Start Server");
	signal(SIGINT, signal_catch);
	int fdout, fdin;
	serverLog("Creo le FIFO!");
	mkfifo("ServerToClient", FILE_MODE);
	mkfifo("ClientToServer", FILE_MODE);
	char buf[MAX_BUF];
	char secret_key[MAX_BUF];
	int eseguicritt = 1;
	int primogiro = 1;
	int primacritt_k =1;
	//apro le fifo
	serverLog("Apro le FIFO! In ATTESA!");
	fdin = open("ClientToServer",  O_RDWR|O_SYNC);
	fdout = open("ServerToClient",  O_RDWR|O_SYNC);
	int n=0;
	while (1) {
		if (primogiro) {
			//ricevo la chiave
			read(fdin, &secret_key, MAX_BUF);
			serverLog("Chiave ricevuta!");
			//ricevo op da eseguire
			read(fdin, &eseguicritt, sizeof(int));
			serverLog("Operazione da eseguire ricevuta!");
			//se eseguo una scrittura prelevo e critto il random e lo invio
			if (eseguicritt) {
				int lenKye = strlen(secret_key); 
				memset(buf, 0, MAX_BUF);
				int r = open("/dev/urandom", O_RDONLY|O_SYNC); //con /dev/random si blocca xke in virtual machine non si muove il mouse
				read(r, &buf,lenKye );
				close(r);
				crypt(buf, secret_key, lenKye, primacritt_k);
				write(fdout, &buf, lenKye);
				serverLog("Array random inviato!");
				primacritt_k = 0;
			}
			primogiro = 0;   
		}
		int brc = read(fdin, &buf, MAX_BUF);
		serverLog("Dati Letti!");
		if (primacritt_k) {
			//entriamo la prima volta nella decrittazione
			crypt(buf, secret_key, brc, primacritt_k);
			primacritt_k = 0;
			//assumiamo che la chiave sia piu corta di maxbuf quindi dobbiamo togliere i byte random all inizio di buf
			write(fdout, &(buf[strlen(secret_key)]), (MAX_BUF - strlen(secret_key))); 
			serverLog("In decrittazione, inviati dati senza array random!");
		} else {
			//in questo caso abbiamo passato il random
			crypt(buf, secret_key, brc, primacritt_k);
			write(fdout, &buf, brc); 
			serverLog("Dati inviati!");
		}
		if (brc < MAX_BUF) {
			//chiudo e riapro
			primogiro = 1;  
			primacritt_k = 1;
			close(fdout);
			close(fdin);
			serverLog("Chiudo e riapro le FIFO! IN ATTESA!");
			fdin = open("ClientToServer",  O_RDWR|O_SYNC);
			fdout = open("ServerToClient",  O_RDWR|O_SYNC);
		}
	}

}

